<?php

	/**
	 * @see Bike_Initial
	 */
	require_once 'Bike/Initial.php';
	
	/**
	 * @see Bike_Controller_Router_Handler_Interface
	 */
	require_once 'Bike/Controller/Router/Handler/Interface.php';
	
	
	class Bike_Format extends Bike_Initial implements Bike_Controller_Router_Handler_Interface
	{
		const DEFAULT_FORMAT = 'html';

		static protected $_instance;

		protected $_default = self::DEFAULT_FORMAT;
		protected $_name;
		protected $_accessorDelimiter = '/';
		protected $_format;
		protected $_accessors;

		static public function getInstance()
		{			if(is_null(self::$_instance))
			{				self::$_instance = new self();
			}
			return self::$_instance;
		}

		public function setDefault($Format)
		{			$this->_default = $Format;
			return $this;
		}

		public function getDefault()
		{
			return $this->_default;
		}

		public function getName()
		{
			return $this->_name;
		}

		public function setName($Name)
		{
			$this->_name = $Name;
			return $this;
		}

		public function getAccessorDelimiter()
		{
			return $this->_accessorDelimiter;
		}

		public function setAccessorDelimiter($AccessorDelimiter)
		{
			$this->_accessorDelimiter = $AccessorDelimiter;
			return $this;
		}

		public function getAccessorWithDelimiter($Accessor)
		{
			if(substr($Accessor, 0, strlen($this->getAccessorDelimiter())) != $this->getAccessorDelimiter())
        	{
        		$Accessor = $this->getAccessorDelimiter().$Accessor;
        	}
        	return $Accessor;
		}

		public function getRouteParam()
		{
			return array($this->getName() => $this->getValue());
		}

	    public function isDefaultFormat()
	    {	    	return ($this->getFormat() == $this->getDefault());
	    }

		public function getFormat()
		{			return is_null($this->_format) ? $this->getDefault() : $this->_format;
		}

		public function setFormat($Format)
		{
			$this->_format = $Format;
			return $this;
		}

		public function setAccessors($Accessors=array())
		{
			$this->_accessors = (array) $Accessors;
			return $this;
		}

		public function getAccessors($Format=null)
		{
			if(is_null($this->_accessors))
			{				$this->setAccessors();
			}
			if(!is_null($Format))
			{				if(!isset($this->_accessors[$Format]))
				{					Throw new Bike_Controller_Router_Handler_Exception('Undefined format "'.$Format.'"');
				}
				return $this->_accessors[$Format];
			}
			return (array) $this->_accessors;
		}

		public function getAccessor($Format)
		{
			$accessors = $this->getAccessors();
			if(!isset($accessors[$Format]))
			{
				Throw new Bike_Controller_Router_Handler_Exception('Undefined format "'.$Format.'"');
			}
			return $accessors[$Format];
		}

		public function route(Zend_Controller_Request_Abstract $Request)
		{         	$pathInfo = $Request->getPathInfo();
        	$this->setFormat($this->getDefault());
        	foreach($this->getAccessors() as $format => $accessor)
        	{
	        	$accessor = $this->getAccessorWithDelimiter($accessor);
	        	$len = strlen($accessor);
	        	if(substr($pathInfo, 0, $len) == $accessor)
	        	{
	        		$this->setFormat($format);
	        		break;
	        	}
        	}
        	if($this->getFormat() != $this->getDefault())
        	{
	        	$Accessor = $this->getAccessorWithDelimiter($this->getAccessors($this->getFormat()));
	        	$Request->setPathInfo(substr($pathInfo, strlen($Accessor)));
        	}
        	return $this->getRouteParam();
		}

		public function getValue()
		{
			return $this->getFormat();
		}

		public function assemble(array $Params)
		{
			$Value = $this->getFormat();
			if(isset($Params[$this->getName()]))
			{
				$Value = $Params[$this->getName()];
			}

			try
			{
				return $this->getAccessor($Value);
			}
			catch(Bike_Controller_Router_Handler_Exception $e)
			{
			}
		}

		protected function isFormat($Format)
	    {
	    	$Format = Bike_String::factory($Format)->lowerCaseFirst();
	    	return (bool) ($this->getFormat() == $Format);
	    }

	    public function __call($Method, $Args)
	    {	    	if(preg_match('/^is([\w\d]+)Format$/', $Method, $matches))
	    	{
                return $this->isFormat($matches[1]);
	    	}
	    	return parent::__call($Method, $Args);
	    }

		public function __toString()
		{			if(!$this->isDefaultFormat())
			{
				return $this->getAccessors($this->getFormat());
			}
		}
	}
